package com.whfc.common.util;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.crypto.*;
import javax.crypto.spec.SecretKeySpec;
import java.nio.charset.Charset;
import java.security.InvalidKeyException;
import java.security.Key;
import java.security.NoSuchAlgorithmException;

/**
 * @Description:
 * @author: xugcheng
 * @version: 1.0
 * @date: 2019/9/19 10:15
 */
public class AESUtil {

    public static final String ALGORITHM = "AES/ECB/PKCS5Padding";

    public static final int keyLength = 128;

    private static final Charset DEFAULT_CHARSET = Charset.forName("UTF-8");

    private static Logger logger = LoggerFactory.getLogger(AESUtil.class);

    /**
     * 生成秘钥
     *
     * @return
     * @throws Exception
     */
    public static byte[] generateKey() {

        try {
            // 生成key
            KeyGenerator keyGenerator;
            //构造密钥生成器，指定为AES算法,不区分大小写
            keyGenerator = KeyGenerator.getInstance("AES");
            //生成一个128位的随机源,根据传入的字节数组
            keyGenerator.init(keyLength);
            //产生原始对称密钥
            SecretKey secretKey = keyGenerator.generateKey();

            //获得原始对称密钥的字节数组
            byte[] keyBytes = secretKey.getEncoded();
            return keyBytes;
        } catch (NoSuchAlgorithmException e) {
            return null;
        }

    }

    /**
     * 加密
     *
     * @param plainText   需要加密的明文
     * @param aesKeyBytes 加密用密钥
     * @return
     */
    public static String encrypt(String plainText, byte[] aesKeyBytes) {

        String cipherText = null;
        try {
            Key key = new SecretKeySpec(aesKeyBytes, "AES");
            Cipher cipher = Cipher.getInstance(ALGORITHM);
            cipher.init(cipher.ENCRYPT_MODE, key);
            byte[] plainBytes = plainText.getBytes(DEFAULT_CHARSET);
            byte[] cipherBytes = cipher.doFinal(plainBytes);
            cipherText = Base64Util.encodeToString(cipherBytes);

        } catch (NoSuchAlgorithmException e) {
            logger.error("", e);
        } catch (NoSuchPaddingException e) {
            logger.error("", e);
        } catch (InvalidKeyException e) {
            logger.error("", e);
        } catch (IllegalBlockSizeException e) {
            logger.error("", e);
        } catch (BadPaddingException e) {
            logger.error("", e);
        }
        return cipherText;
    }

    /**
     * 解密
     *
     * @param cipherText  加密后的密文
     * @param aesKeyBytes 解密用密钥
     */
    public static String decrypt(String cipherText, byte[] aesKeyBytes) {
        String plainText = null;
        try {
            Key key = new SecretKeySpec(aesKeyBytes, "AES");
            Cipher cipher = Cipher.getInstance(ALGORITHM);
            cipher.init(Cipher.DECRYPT_MODE, key);
            byte[] cipherBytes = Base64Util.decode(cipherText);
            byte[] plainBytes = cipher.doFinal(cipherBytes);
            plainText = new String(plainBytes, DEFAULT_CHARSET);
        } catch (NoSuchAlgorithmException e) {
            logger.error("", e);
        } catch (NoSuchPaddingException e) {
            logger.error("", e);
        } catch (InvalidKeyException e) {
            logger.error("", e);
        } catch (IllegalBlockSizeException e) {
            logger.error("", e);
        } catch (BadPaddingException e) {
            logger.error("", e);
        }

        return plainText;
    }


    public static void main(String[] args) throws Exception {

        byte[] aesKeyBytes = generateKey();
        String aesKey = Base64Util.encodeToString(aesKeyBytes);

        aesKey = "0123456789012345";
        aesKeyBytes = aesKey.getBytes("utf-8");

        System.out.println("秘钥:" + aesKey);

        //
        String plainText1 = "abcdefg123456abcdefg123456";
        String cipherText = encrypt(plainText1, aesKeyBytes);
        String plainText2 = decrypt(cipherText, aesKeyBytes);

        System.out.println("明文:" + plainText1);
        System.out.println("密文:" + cipherText);
        System.out.println("明文:" + plainText2);
    }
}
